package com.sh.data.engine.domain.base.service.impl;

import com.sh.data.engine.common.util.ServletUtils;
import com.sh.data.engine.domain.base.model.ChunkFileUploadDomain;
import com.sh.data.engine.domain.base.model.FileUploadResultDomain;
import com.sh.data.engine.domain.base.model.FileUrlDomain;
import com.sh.data.engine.domain.base.model.param.ChunkFileUploadParam;
import com.sh.data.engine.domain.base.service.FileService;
import com.sh.data.engine.infrastructure.config.MinioConfiguration;
import com.sh.data.engine.infrastructure.storage.MinioClientService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.UUID;

/**
 * @author: mengzheng.mhc
 * @date: 2024/6/11 11:21
 */
@Slf4j
@Service
@ConditionalOnProperty(value = "data.engine.file-storage.type", havingValue = "minio")
public class MinioFileServiceImpl implements FileService {

    @Autowired
    private MinioClientService minioClientService;

    @Autowired
    private MinioConfiguration minioConfiguration;

    @Autowired
    private Environment environment;

    @Override
    public FileUploadResultDomain upload(MultipartFile multipartFile) throws Exception {
        return upload(multipartFile, null, false);
    }

    @Override
    public FileUploadResultDomain upload(MultipartFile multipartFile, boolean uuidFileName)
        throws Exception {
        return upload(multipartFile, null, uuidFileName);
    }

    @Override
    public FileUploadResultDomain upload(MultipartFile multipartFile, String fileRelativeDirPath)
        throws Exception {
        return upload(multipartFile, fileRelativeDirPath, false);
    }

    @Override
    public FileUploadResultDomain upload(
        MultipartFile multipartFile, String fileRelativeDirPath, boolean uuidFileName)
        throws Exception {
        FileUploadResultDomain domain = new FileUploadResultDomain();

        final String originalFilename = multipartFile.getOriginalFilename();
        String fileDir = "/";

        if (StringUtils.isNotBlank(fileRelativeDirPath)) {
            fileDir = fileRelativeDirPath;
        }

        String fileName = originalFilename;

        if (uuidFileName) {
            String suffix =
                originalFilename.contains(".")
                    ? originalFilename.substring(originalFilename.lastIndexOf("."))
                    : "";
            fileName = UUID.randomUUID() + suffix;
        }

        minioClientService.putObject(
            minioConfiguration.getFileStorageBucketName(),
            fileDir,
            fileName,
            multipartFile.getInputStream());

        domain.setOriginalFilename(originalFilename);
        domain.setFileName(fileName);
        domain.setFilePath(fileDir + "/" + fileName);

        final String contextPath = environment.getProperty("server.servlet.context-path", "");

        final HttpServletRequest request = ServletUtils.getRequest();
        String uriPrefix =
            request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();

        final String decode = URLDecoder.decode(domain.getFilePath(), "UTF-8");

        String filePreviewUrl = uriPrefix + contextPath + "/api/v1/file/getFileForPreview?filePath=" + decode;
        String fileDownloadUrl =
            uriPrefix + contextPath + "/api/v1/file/getFileForDownload?filePath=" + decode;

        domain.setFileDownloadUrl(fileDownloadUrl);
        domain.setFilePreviewUrl(filePreviewUrl);

        return domain;
    }

    @Override
    public FileUploadResultDomain uploadHiveSite(
        MultipartFile multipartFile, String fileRelativeDirPath, boolean uuidFileName)
        throws Exception {
        return null;
    }

    @Override
    public ChunkFileUploadDomain uploadByChunk(
        javax.servlet.http.HttpServletRequest request, ChunkFileUploadParam param) {
        return null;
    }

    @Override
    public File getFileByPath(String filePath) {

        String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
        final File file =
            minioClientService.downloadFile(
                minioConfiguration.getFileStorageBucketName(), filePath, fileName);
        return file;
    }

    @Override
    public FileUrlDomain getFileUrlByPath(String filePath, javax.servlet.http.HttpServletRequest request) {
        if (null == filePath) {
            return null;
        }
        FileUrlDomain domain = new FileUrlDomain();

        final String contextPath = environment.getProperty("server.servlet.context-path", "");

        String uriPrefix =
            request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();

        String decode = "";
        try {
            decode = URLDecoder.decode(filePath, "UTF-8");
        } catch (UnsupportedEncodingException e) {

        }

        String filePreviewUrl = uriPrefix + contextPath + "/api/v1/file/getFileForPreview?filePath=" + decode;
        String fileDownloadUrl =
            uriPrefix + contextPath + "/api/v1/file/getFileForDownload?filePath=" + decode;

        domain.setFileDownloadUrl(fileDownloadUrl);
        domain.setFilePreviewUrl(filePreviewUrl);

        return domain;
    }
}
